﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using TCC_Hotel.Repositorio;
using TCC_Hotel.Entidades;
using System.Web.Caching;
using TCC_Hotel.Serviços.OtherServices;

namespace TCC_Hotel.Serviços.BDServices
{
    public class EstoqueService
    {
        EstoqueRepositorio repositorio = new EstoqueRepositorio();


        /// <summary>
        /// Serviço para compra de produto. Incrementa a quantidade de produto em estoque 
        /// de acordo com a quantidade comprada
        /// </summary>
        /// <param name="quantidade">quantidade que será incrementada</param>
        /// <returns>True se foi incrementada ou false se nao</returns>
        public bool ComprarProduto(int quantidade, int ID)
        {
            return repositorio.ComprarProduto(quantidade, ID);

        }

        /// <summary>
        /// Serviço que incrementa a quantidade em estoque devido ao cancelamento de uma venda
        /// </summary>
        /// <param name="quantidade">quantidade que será incrementada</param>
        /// <returns>True se foi incrementada ou false se nao</returns>
        public bool IncrementarEstoqueProduto(int quantidade, string Produto)
        {
            return repositorio.IncrementarEstoqueProduto(quantidade, Produto);

        }

        /// <summary>
        /// Serviço para venda de produto. Decrementa a quantidade de produto em estoque 
        /// de acordo com a quantidade vendida e verifica estoque minimo
        /// </summary>
        /// <param name="quantidade">quantidade que será decrementada</param>
        /// <returns>True se foi decrementada ou false se nao</returns>
        public bool VenderProduto(int quantidade, int ID)
        {
            bool venda = repositorio.VenderProduto(quantidade, ID);
            Produto produto = repositorio.RecuperarDetalhesProdutoEstoque(ID);            

            //Verifica se com a venda o produto atingiu o estoque mínimo possivel
            //se atingiu, é chamado o serviço de envio de email para o fornecedor correspondente
            //se for permitido
            if (produto.QuantidadeEstoque < produto.QuantidadeMinima && produto.PermitirEnvioEmail && venda && !produto.SolicitacaoEnviada)
            {
                ExternalService servico_Externo = new ExternalService();
                FornecedorService servico_Fornecedor = new FornecedorService();
                Fornecedor fornecedor = servico_Fornecedor.RecuperarDetalhesFornecedor(produto.IDFornecedor);
                string emailFornecedor = fornecedor.EmailFornecedor;
                string corpoEmail = "Solicitação de SIGHO:\n Olá responsável pelo fornecedor " + fornecedor.NomeFornecedor + ". \nSolicitamos a compra de " + produto.QuantidadePedido + " unidades do produto: " +
                    produto.NomeProduto + ".\n\nObrigado e quaisquer dúvidas estamos a disposição";

                //serviço de envio de email
                servico_Externo.EnviarEmailFornecedor(emailFornecedor, corpoEmail);
                repositorio.EditarSolicitacaoEnviada(true, produto.ID);

                              
            }

            
            return venda;

        }

        /// <summary>
        /// Serviço para listar todos os Produtos do estoque no banco
        /// </summary>
        /// <returns>Lista com os Produtos do banco</returns>
        public List<Produto> RecuperarProdutosEstoque()
        {
            return repositorio.RecuperarProdutosEstoque().OrderBy(i => i.NomeProduto).ToList();

        }

         /// <summary>
        /// Serviço para recuperar um produto do estoque
        /// </summary>
        /// <returns>produto solicitado</returns>
        public Produto RecuperarDetalhesProdutoEstoque(int ID)
        {
            return repositorio.RecuperarDetalhesProdutoEstoque(ID);

        }
        
         /// <summary>
        /// Serviço para editar a quantidade de um produto do banco 
        /// </summary>
        /// <returns>true se editou e false se nao</returns>
        public bool EditarQuantidadeProduto(int ID, int nova_Quantidade)
        {
            return repositorio.EditarQuantidadeProduto(ID, nova_Quantidade);
        }

        /// <summary>
        /// Lista todos os produtos que não estão com estoque 0
        /// </summary>
        /// <returns>Lista de Produtos</returns>
        public List<Produto> ListarProdutosDisponiveisCache()
        {
            return ListarProdutosEstoqueCache().Where(i => i.QuantidadeEstoque > 0).ToList();
        }

        /// <summary>
        /// Verifica se a informação ja esta gravada em cache, se tiver recupera, 
        /// senao faz a consulta e grava em cache
        /// </summary>
        /// <returns>Lista de Produtos</returns>
        public List<Produto> ListarProdutosEstoqueCache()
        {
            List<Produto> produtos = new List<Produto>();

            //Verifica se a informação esta guardada em cache
            if (HttpContext.Current.Cache.Get("Lista_Produtos_Estoque") == null)
            {
                //Consulta os Produtos no banco
                produtos = RecuperarProdutosEstoque();

                //Armazena a lista de Produtos em cache de 1 minuto para evitar muitas consultas ao banco
                HttpContext.Current.Cache.Add("Lista_Produtos_Estoque", produtos, null,
                                 DateTime.Now.AddMinutes(5), Cache.NoSlidingExpiration, CacheItemPriority.High, null);

            }

           //caso essa informaçao ja estiver no cache
            else
            {
                //Resgata informação do cache
                produtos = (List<Produto>)HttpContext.Current.Cache.Get("Lista_Produtos_Estoque");

            }

            return produtos;

        }

        /// <summary>
        /// Serviço para listar todos os Produtos faltantes do estoque no banco
        /// </summary>
        /// <returns>Lista com os Produtos faltantes do banco</returns>
        public List<Produto> RecuperarProdutosFaltantesEstoque()
        {
            return repositorio.RecuperarProdutosFaltantesEstoque().OrderBy(i => i.NomeProduto).ToList();

        }

        /// <summary>
        /// Verifica se a informação ja esta gravada em cache, se tiver recupera, 
        /// senao faz a consulta e grava em cache
        /// </summary>
        /// <returns>Lista de Produtos</returns>
        public List<Produto> ListarProdutosFaltantesEstoqueCache()
        {
            List<Produto> produtos = new List<Produto>();

            //Verifica se a informação esta guardada em cache
            if (HttpContext.Current.Cache.Get("Lista_Produtos_Estoque_Faltantes") == null)
            {
                //Consulta os Produtos no banco
                produtos = RecuperarProdutosFaltantesEstoque();

                //Armazena a lista de Produtos em cache de 1 minuto para evitar muitas consultas ao banco
                HttpContext.Current.Cache.Add("Lista_Produtos_Estoque_Faltantes", produtos, null,
                                 DateTime.Now.AddMinutes(5), Cache.NoSlidingExpiration, CacheItemPriority.High, null);

            }

           //caso essa informaçao ja estiver no cache
            else
            {
                //Resgata informação do cache
                produtos = (List<Produto>)HttpContext.Current.Cache.Get("Lista_Produtos_Estoque_Faltantes");

            }

            return produtos;

        }


    }
}